Spring是如何解决循环依赖(引用)的?

您所在的位置:网站首页 spring 解决循环引用 Spring是如何解决循环依赖(引用)的?

Spring是如何解决循环依赖(引用)的?

2023-10-17 19:02| 来源: 网络整理| 查看: 265

首先什么是循环依赖,比如A->B->A,正常我们普通的类怎么解决呢,就是先  new A(),new B() ,然后再 setB,setA ,也比较好解决。

那么大家为什么会经常提到spring循环依赖呢,我认为主要有两个原因:

spring的bean是一个一个加载的,A创建的过程中,发现依赖B,B还没创建,就会去先创建B spring的bean有一个较复杂的生命周期,它的bean常常需要被生成代理 那spring是如何解决这个循环依赖问题的呢?

spring的核心思想同样是:先实例化,后设置属性。它内部维护了三个map,就是网上常说的三级缓存。

一个是 singletonObjects  map ,也就是我们说的单例池,它存放的是已经完成实例化的完成的bean;

一个是 singletonFactories  map,二级缓存,它是解决循环依赖的关键,也就是存放未完全创建的对象工厂ObjectFactory,它持有原对象的引用;

一个是 earlySingletonObjects  map,三级缓存,它是存放经过ObjectFactory.getObject,生成的早期单例对象存在这个map中,这里面的对象可能是个代理类。

 singletonFactories  、 earlySingletonObjects  中的对象都还不是完整的bean,都还没有进行属性的注入,以及初始化过程。

 

注:很多文章会称 singletonFactories 为三级缓存, earlySingletonObjects 为二级缓存,这里其实没有谁对谁错,只是个叫法,不用纠结。

说明:原型(Prototype)的场景、通过构造方法进行依赖注入,这两种情况循环依赖都没有解决

spring的解决循环依赖的大概过程

 创建A,先把A通过构造方法反射实例化得到一个空的对象,然后根据是否单例,是否允许循环引用,如果是的话,包装一个 ObjectFactory 对象,加到 singletonFactories  map中,然后进行A的属性设置,这时候发现A的属性B还没创建,转而先去创建B,同样的,先把B加到 singletonFactories  map中,设置B的属性的时候,发现A还没创建,又转而去创建A,此时A已经在 singletonFactories ,然后调用A的ObjectFactory中的getObject方法,获取A的早期引用(生成的可能是个代理对象,此时A还没实例完全,属性还没设置),然后会把A转移到earlySingletonObjects map中(),接着继续执行B的属性填充等初始化过程,B的创建过程完成,将B加到单例池中。B创建完之后,回到A的创建过程,进行属性填充,将B设置到A上,完成A的初始化过程,完后将A从earlySingletonObjects中取出,加到singletonObjects 单例池中。至此,循环依赖过程结束后。

 为什么第二级缓存要使用ObjectFactory?

为了这个bean能够被一些beanPostProcessor处理,使其能够创建为代理对象。

三级缓存earlySingletonObjects 的作用是什么?

存储ObjectFactory.getObject()之后生成的半成品对象(这个对象只是原本的实例化,或者代理对象,没有经历过属性注入与初始化过程),用于保存真实的对象引用,因为真正要放到单例池中的对象可能是个代理对象。

 postProcessAfterInitialization也可以生成代理,ObjectFactory.getObject()生成代理后,再执行postProcessAfterInitialization,岂不是会执行两遍生成代理流程?

debug发现,ObjectFactory.getObject()返回的确实是代理对象(如果需要的话),后续在执行postProcessAfterInitialization的时候,会有个earlyProxyReferences的判断,直接返回原对象,在后面流程中,会从earlySingletonObjects 中取代理后的对象,放到单例池中。

说明,debug发现: B只会经过singletonFactories 、singletonObjects ,不经过earlySingletonObjects 如果A需要生成代理对象,那生成的代理对象中的属性值为null,如:A->B->$proxyA->b=null,单例池中存放的是代理后的A 如果A不需要生成代理对象,那么关系就是 A->B->A->B....,形成循环依赖  关键源码:

注:只列出与循环依赖相关的关键代码

// org.springframework.beans.factory.support.AbstractBeanFactory protected T doGetBean( String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 获取单例bean,首次进来为null Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { ... } else { ... // Create bean instance. if (mbd.isSingleton()) { // 获取单例对象,没有则执行创建,第二个参数为ObjectFactory sharedInstance = getSingleton(beanName, () -> { try { // 创建bean return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); } } } // org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ... if (instanceWrapper == null) { // 实例化bean instanceWrapper = createBeanInstance(beanName, mbd, args); } ... // 是否单例,是否可以循环引用,是否是正在创建中的单例对象 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 提前暴露工厂对象,将ObjectFactory添加到singletonFactories中 // getEarlyBeanReference返回的对象会经过一些BeanPostProcessor的处理,可能生成对应的代理对象,如果不需要代理,则基本都是原对象 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } ... // 属性注入,如果发现有依赖的bean,并且未创建,回去先创建依赖的bean populateBean(beanName, mbd, instanceWrapper); // 初始化回调流程 exposedObject = initializeBean(beanName, exposedObject, mbd); ... if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) // 这个地方会把原对象,替换成代理对象 exposedObject = earlySingletonReference; } } } // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator // 上面的getEarlyBeanReference方法中调用的 @Override public Object getEarlyBeanReference(Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this.earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); } // bean生命周期中initializeBean方法中的流程,一般AOP代理也在这边生成 @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); // 代理对象的话,这边不会进入if if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } // org.springframework.beans.factory.support.DefaultSingletonBeanRegistry public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /**(一级缓存)已经完成加载的单例缓存.*/ private final Map singletonObjects = new ConcurrentHashMap(256); /**(三级缓存)早期的单例对象缓存集合. 存储二级缓存加工过的对象,此时该Bean还未构建完成 */ private final Map earlySingletonObjects = new HashMap(16); /**(二级缓存)单例的工厂Bean缓存集合. */ private final Map singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } }

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3